/*
 * MIT License
 *
 * Copyright (c) 2020 wen.gu <454727014@qq.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

/***************************************************************************
 * Name: mp_media.h
 *
 * Purpose: the media data type for micro player
 *
 * Developer:
 *   wen.gu , 2018-09-03
 *
 * TODO: 
 *
 ***************************************************************************/
#ifndef __MP_MEDIA_H__
#define __MP_MEDIA_H__

/******************************************************************************
**    INCLUDES
******************************************************************************/
#include <memory>
#include "mp_types.h"

/******************************************************************************
**    MACROS
******************************************************************************/
#define INVALID_TIMESTAMP (-1)

#define MAKE_SHARED_ARRAY8(size) std::shared_ptr<uint8_t>(new uint8_t[size](), std::default_delete<uint8_t[]>())
/******************************************************************************
**    TYPE DEFINITIONS
******************************************************************************/
enum class eMediaCategory: uint8_t
{
    Unknown = 0,
    Audio,
    Video,
};

enum class eContainerFormat: uint32_t
{
    Unknown = 0, /**< Placeholder value when container is N/A */
    MP4 = GFCC('c', 'M', 'P', '4'),
};

/** the type of frame */
enum class eFrameType:uint8_t
{
    Unknown,  /**< Placeholder value when frame type is N/A */
    I,
    P,
    B,
};


enum class eMediaFormat: uint32_t
{
    Unknown = 0, /**< Placeholder value when media format is N/A */

    /** video codec type */
    AVC                 = GFCC('H', '2', '6', '4'),  /**< H.264/AVC */

    /** video raw data type */
    YUV420Planar        = GFCC('I', '4', '2', '0'),
    YUV420PackedPlanar  = GFCC('4', '2', '0', 'p'),
    YUV420SemiPlanar    = GFCC('N', 'V', '1', '2'),


    /** audio codec type */
    AAC                 = GFCC('m', 'p', '4', 'a'), /**< Any variant of AAC encoded data */
    Vorbis              = GFCC('v', 'r', 'b', 's'), /** vorbis audio */
    MP3                 = GFCC('m', 'p', '3', 'a'), /** mp3 audio format */

    /** audio raw data type */
    S8                  = GFCC('s', '8', ' ', ' '),
    U8                  = GFCC('u', '8', ' ', ' '),
    S16L                = GFCC('s', '1', '6', 'l'),
    S16LP               = GFCC('s', '1', '6', 'p'), /**< planar sample layout */
    S16B                = GFCC('s', '1', '6', 'b'),
    U16L                = GFCC('u', '1', '6', 'l'),
    U16B                = GFCC('u', '1', '6', 'b'),
    S20B                = GFCC('s', '2', '0', 'b'),
    S24L                = GFCC('s', '2', '4', 'l'),
    S24B                = GFCC('s', '2', '4', 'b'),
    U24L                = GFCC('u', '2', '4', 'l'),
    U24B                = GFCC('u', '2', '4', 'b'),
    S24L32              = GFCC('s', '2', '4', '4'),
    S24B32              = GFCC('S', '2', '4', '4'),
    S32L                = GFCC('s', '3', '2', 'l'),
    S32B                = GFCC('s', '3', '2', 'b'),
    U32L                = GFCC('u', '3', '2', 'l'),
    U32B                = GFCC('u', '3', '2', 'b'),
    F32L                = GFCC('f', '3', '2', 'l'),
    F32B                = GFCC('f', '3', '2', 'b'),
    F64L                = GFCC('f', '6', '4', 'l'),
    F64B                = GFCC('f', '6', '4', 'b'),
};

enum class eSeekMode : uint8_t
{
    PreviousSync = 0,
    NextSync,
    ClosestSync
};

using SharedArray8 = std::shared_ptr<uint8_t>;


///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

struct MPVideoInfo
{
    uint32_t picWidth = 0;  /** picture width */
    uint32_t picHeight = 0; /** picture hight */
    uint32_t bufWidth = 0;  /** buffer stride */
    uint32_t bufHeight = 0; /** buffer height */
    uint32_t framerate = 0; /** fps(frame per second) */
};

struct MPAudioInfo
{
    uint32_t samplerate = 0;   /** how many samples per second */
    uint32_t channelCount = 0; /** channel count */
    uint32_t bitDepth = 0;     /** how many bits per sample */
};


struct MPTrackInfo
{
    /**
     * track identifier, where means
     * -1: let the core mark the right id
     * >=0: valid id
     */
    int32_t id = -1;
    /**
     * group identifier, where means:
     * -1 : standalone
     * >= 0 then a "group" (program) is created for each value
     */
    int32_t group = -1;
    
    eMediaCategory category = eMediaCategory::Unknown;
    eMediaFormat format = eMediaFormat::Unknown;
    uint32_t fourcc = 0; /** original fourcc from the container */
    uint8_t language[4] = {0}; /** human readible language name */

    uint32_t bit_rate = 0; /** how many bits data per second, bps */

    uint32_t extraSize = 0; /** the size of extra data[optinal] */
    SharedArray8 extraData = nullptr; /** extar data pointer[optional] */

    /** format detail information */
    MPAudioInfo audio;
    MPVideoInfo video;
};

struct MPContainerInfo
{
    eContainerFormat fmt = eContainerFormat::Unknown;  
    /** the start time of first video or video frame pts 
     *  of current container(in milli-second) 
     */
    int64_t startTimeMs = INVALID_TIMESTAMP; 
    int64_t durationMs = INVALID_TIMESTAMP;  /** the total duration time of current container */
    
};

/******************************************************************************
**    CLASSES/FUNCTIONS DEFINITIONS
******************************************************************************/

#endif /** !__MP_MEDIA_H__*/


 

